/*
 * Torre.cpp
 *
 *  Created on: 20/04/2013
 *      Author: gonzalo
 */

#include "Torre.h"

Torre::Torre(GLuint program, GLfloat largo_cubos, GLfloat ancho_cubos) :
		Figure(program) {

	// FIJO LAS DIMENSIONES
	//ancho_cubos = 0.1;
	//largo_cubos = 1.5;

	for (int i = 0; i < 15; i++) {
		cubos_base[i] = new CuboTorre(program, largo_cubos, ancho_cubos);
		cubos_base[i]->traslate(glm::vec3(0.0, 0.0, largo_cubos * i));
	}
	for (int i = 0; i < 15; i++) {
		cubos_grua[i] = new CuboTorre(program, largo_cubos, ancho_cubos);
		cubos_grua[i]->traslate(glm::vec3(largo_cubos * (i - 4), 0.0, largo_cubos * 15));
		cubos_grua[i]->traslate(glm::vec3(0.0, 0.0, largo_cubos / 2));
		cubos_grua[i]->rotate(90, glm::vec3(0.0, 1.0, 0.0));
		cubos_grua[i]->traslate(glm::vec3(0.0, 0.0, -largo_cubos / 2));
	}
	for (int i = 0; i < 5; i++) {
		cubos_final_grua[i] = new Cube(program);
	}
	cubo_cabina = new Cube(program);
	cubo_contrapeso = new Cube(program);

	altura_cabina = largo_cubos * 15 + largo_cubos / 2;
	ancho_cabina = 2 * largo_cubos;

	cubo_cabina->traslate(glm::vec3(0.0, 0.0, altura_cabina));
	cubo_cabina->scale(glm::vec3(1.8 * largo_cubos, 2 * largo_cubos, 1.25 * largo_cubos));
	cubo_contrapeso->traslate(glm::vec3(-4.25 * largo_cubos, 0.0, largo_cubos * 15 + largo_cubos / 2));
	cubo_contrapeso->scale(glm::vec3(0.8 * largo_cubos, 1.25 * largo_cubos, 1.25 * largo_cubos));
	for (int i = 0; i < 5; i++) {
		cubos_final_grua[i]->traslate(
				glm::vec3(10 * largo_cubos + largo_cubos / 2, 0.0, largo_cubos * 15 + largo_cubos / 2));
		cubos_final_grua[i]->rotate(90, glm::vec3(0.0, 1.0, 0.0));
	}
	cubos_final_grua[0]->traslate(glm::vec3(0, -largo_cubos / 2, 0));
	cubos_final_grua[0]->rotate(45, glm::vec3(1, 0, 0));
	cubos_final_grua[0]->scale(glm::vec3(largo_cubos, ancho_cubos, ancho_cubos));

	cubos_final_grua[1]->traslate(glm::vec3(0, largo_cubos / 2, 0));
	cubos_final_grua[1]->rotate(45, glm::vec3(1, 0, 0));
	cubos_final_grua[1]->scale(glm::vec3(largo_cubos, ancho_cubos, ancho_cubos));

	cubos_final_grua[2]->traslate(glm::vec3(-largo_cubos / 2, 0, 0));
	cubos_final_grua[2]->rotate(90, glm::vec3(0, 0, 1));
	cubos_final_grua[2]->rotate(45, glm::vec3(1, 0, 0));
	cubos_final_grua[2]->scale(glm::vec3(largo_cubos, ancho_cubos, ancho_cubos));

	cubos_final_grua[3]->traslate(glm::vec3(largo_cubos / 2, 0, 0));
	cubos_final_grua[3]->rotate(90, glm::vec3(0, 0, 1));
	cubos_final_grua[3]->rotate(45, glm::vec3(1, 0, 0));
	cubos_final_grua[3]->scale(glm::vec3(largo_cubos, ancho_cubos, ancho_cubos));

	//cubos_final_grua[4]->traslate(glm::vec3(largo_cubos / 2, 0, 0));
	cubos_final_grua[4]->rotate(45, glm::vec3(0, 0, 1));
	cubos_final_grua[4]->rotate(45, glm::vec3(1, 0, 0));
	cubos_final_grua[4]->scale(glm::vec3(sqrt(largo_cubos * largo_cubos * 2), ancho_cubos, ancho_cubos));

	angulo_rotacion_grua = 0.0;
}

Torre::~Torre() {
	for (int i = 0; i < 15; i++) {
		delete cubos_base[i];
	}
}

void Torre::draw_base(GLuint program, glm::mat4 & world_matrix) {
	for (int i = 0; i < 15; i++) {
		cubos_base[i]->draw(program,world_matrix);
	}
}

void Torre::draw_grua(GLuint program, glm::mat4 & world_matrix) {
	for (int i = 0; i < 15; i++) {
		cubos_grua[i]->draw(program,world_matrix);
	}
}

void Torre::draw(GLuint program, glm::mat4 & world_matrix) {
	glm::mat4 matriz = world_matrix * this->model_matrix;

	// Bind Model Matrix
	GLuint location_model_matrix = glGetUniformLocation(program, "ModelMatrix");
	if (location_model_matrix >= 0) {
		glUniformMatrix4fv(location_model_matrix, 1, GL_FALSE, &matriz[0][0]);
	}

	draw_base(program,matriz);

	matriz = glm::rotate(matriz, this->angulo_rotacion_grua, glm::vec3(0.0, 0.0, 1.0));

	draw_grua(program,matriz);

	cubo_cabina->draw(program,matriz);
	cubo_contrapeso->draw(program,matriz);

	for (int i = 0; i < 5; i++) {
		cubos_final_grua[i]->draw(program,matriz);
	}
}

void Torre::girar_grua(GLfloat angulo_giro) {
	this->angulo_rotacion_grua += angulo_giro;
}

void Torre::establecer_angulo(GLfloat angulo_giro) {
	this->angulo_rotacion_grua = angulo_giro;
}

GLfloat Torre::get_angulo_grua() {
	return angulo_rotacion_grua;
}

glm::vec3 Torre::get_camera_position(glm::mat4 & world_matrix) {
	glm::vec3 camara;
	glm::mat4 matriz = world_matrix * this->model_matrix;

	GLfloat distancia = 2;
	GLfloat cosPhi = cosf((angulo_rotacion_grua + 90) * PI / 180);
	GLfloat sinPhi = sinf((angulo_rotacion_grua + 90) * PI / 180);

	camara = cubo_cabina->get_transformated_origin(matriz);

	camara.x += distancia * cosPhi;
	camara.y += distancia * sinPhi;

	return camara;
}

void Torre::set_color(const glm::vec3 & color) {
	for (int i = 0; i < 15; i++) {
		cubos_base[i]->set_color(color);
	}
	for (int i = 0; i < 15; i++) {
		cubos_grua[i]->set_color(color);
	}
	for (int i = 0; i < 5; i++) {
		cubos_final_grua[i]->set_color(color);
	}
	cubo_cabina->set_color(color);
	cubo_contrapeso->set_color(color);
}
